package com.whq.knowverywell.task.update;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.widget.Toast;

import com.whq.knowverywell.util.LogUtil;

public class ApkUpdateAsyncTask extends AsyncTask<URL, Integer, Uri> {
	class FileInfo {
		int fileSize;
		long lastModifyTime;
	};

	private static final String TAG = "ApkUpdateAsyncTask";

	public static final long AK_DAY_MILLIS = 24 * 60 * 60 * 1000;

	private static final int PROGRESS_MAX = 100;
	private static String mVersion = "";
	private DownloadResumeInfo resumeInfo = null;

	private Context context;
	private ProgressDialog progressDialog = null;
	public Handler handler = new Handler();
	private ApkUpdateAsyncTask instance;

	public ApkUpdateAsyncTask(Context context) {
		this.context = context;
		instance = this;
	}

	public ApkUpdateAsyncTask(Context context, String version) {
		this.context = context;
		instance = this;
		mVersion = version;

	}

	@Override
	protected Uri doInBackground(URL... urls) {
		return downloadFileFromURL(urls[0], context);
	}

	@Override
	protected void onProgressUpdate(Integer... progress) {
		if (progressDialog == null) {
			LogUtil.d(TAG, "onProgressUpdate");
			progressDialog = new ProgressDialog(context);
			progressDialog.setOnCancelListener(new OnCancelListener() {

				@Override
				public void onCancel(DialogInterface dialog) {
					android.os.Process.killProcess(android.os.Process.myPid());

				}
			});
			progressDialog.setButton("取 消", new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int i) {
					// 点击“确定按钮”取消对话框
					instance.cancel(true);
					resumeInfo.saveResumeInfo();
					progressDialog.dismiss();

				}
			});

			progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			progressDialog.setCancelable(false);
			progressDialog.setTitle("正在更新...");

			progressDialog.setMax(PROGRESS_MAX);
			progressDialog.show();

		}
		progressDialog.setProgress(progress[0]);
	}

	@Override
	protected void onCancelled() {
		if (progressDialog != null)
			progressDialog.dismiss();
		super.onCancelled();
	}

	@Override
	protected void onPostExecute(Uri result) {
		if (progressDialog != null)
			progressDialog.dismiss();
		if (result != null) {
			Intent intent = new Intent(Intent.ACTION_VIEW);
			intent.setDataAndType(result, "application/vnd.android.package-archive");
			context.startActivity(intent);
			android.os.Process.killProcess(android.os.Process.myPid());

		} else {

			String errdown = "访问下载服务器失败，请稍后再试";
			new AlertDialog.Builder(context).setTitle("错误提示").setMessage(errdown)
					.setPositiveButton("知道了", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							instance.cancel(true);
							resumeInfo.saveResumeInfo();
							LogUtil.d(TAG, "updtate fail click");
						}
					}).show();
		}
	}

	FileInfo getFileInfo(URL url) {
		FileInfo fileInfo = new FileInfo();

		HttpURLConnection httpConnection;
		try {
			httpConnection = (HttpURLConnection) url.openConnection();
			HttpURLConnection.setFollowRedirects(true);
			httpConnection.setConnectTimeout(5000);
			httpConnection.setReadTimeout(10000);

			fileInfo.fileSize = httpConnection.getContentLength();
			fileInfo.lastModifyTime = httpConnection.getLastModified();

			httpConnection.disconnect();

		} catch (IOException e) {
			LogUtil.e(TAG, "获取文件[" + url + "]信息失败：", e);
		}

		return fileInfo;
	}

	private Uri downloadFileFromURL(URL url, Context context) {
		try {
			HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
			HttpURLConnection.setFollowRedirects(true);
			httpConnection.setConnectTimeout(5000);
			httpConnection.setReadTimeout(10000);
			if (httpConnection != null) {
				FileInfo fileInfo = getFileInfo(url);
				RandomAccessFile file = getTempFile(context, fileInfo);

				int len, length = resumeInfo.getDownloadedSize();
				byte[] buf = new byte[8192];

				httpConnection.setRequestProperty("Range", "bytes=" + length + "-" + resumeInfo.getFileSize());
				InputStream is = httpConnection.getInputStream();

				try {
					while (isCancelled() == false && (len = is.read(buf, 0, buf.length)) != -1) {
						LogUtil.d(TAG, "downloadFileFromURL  READ LEN =" + len);
						file.write(buf, 0, len);
						length += len;
						resumeInfo.setDownloadedSize(length);
						publishProgress((int) (PROGRESS_MAX * (float) length / fileInfo.fileSize));
					}
					LogUtil.d(TAG, "downloadFileFromURL over len =" + length);
				} catch (IOException e) {
					LogUtil.d(TAG, "downloadFileFromURL  IOException 1");
					this.cancel(true);
					String downloadfail = "更新失败，请稍后再试";
					Toast.makeText(context, downloadfail, Toast.LENGTH_SHORT);

					LogUtil.e(TAG, "下载文件[" + url + "]失败：", e);

					resumeInfo.saveResumeInfo();
					return null;
				} finally {
					is.close();
					file.close();
				}

				if (isCancelled() == false) {
					return resumeInfo.Finish();
				}

				return null;
			}
		} catch (IOException e) {
			LogUtil.d(TAG, "downloadFileFromURL  IOException 2");
			this.cancel(true);
			String downloadfail = "更新失败，请稍后再试";
			Toast.makeText(context, downloadfail, Toast.LENGTH_SHORT);

			LogUtil.e(TAG, "下载文件[" + url + "]失败：", e);
		} catch (Exception e) {
			LogUtil.e(TAG, "下载文件[" + url + "]信息失败：", e);
		}
		return null;

	}

	private RandomAccessFile getTempFile(Context context, FileInfo info) throws IOException, ClassNotFoundException {
		String filePath = Environment.getExternalStorageDirectory() + "/know-very-well_" + mVersion + ".tmp";
		String fileInfo = Environment.getExternalStorageDirectory() + "/know-very-well_" + mVersion + ".info";

		File apkFile = new File(filePath);
		File apkFileInfo = new File(fileInfo);

		// 信息文件和下载的中间 文件都存在时候才从文件中读断点续传信息结点
		if (apkFileInfo.exists() && apkFile.exists()) {
			FileInputStream fis = new FileInputStream(fileInfo);
			ObjectInputStream ois = new ObjectInputStream(fis);
			resumeInfo = (DownloadResumeInfo) ois.readObject();
			// 最后一次修改时间和文件大小发生变化，则抛弃resumeInfo，重新下载
			long curTime = System.currentTimeMillis();
			if (Math.abs(curTime - resumeInfo.getGenerateTime()) > AK_DAY_MILLIS
					|| info.fileSize != resumeInfo.getFileSize()) {
				resumeInfo = null;
			}
		}

		if (resumeInfo == null) {
			resumeInfo = new DownloadResumeInfo();

			resumeInfo.setFileName("know-very-well_" + mVersion + ".apk");
			resumeInfo.setFileSize(info.fileSize);
			resumeInfo.setVersion(mVersion);
			resumeInfo.setDownloadedSize(0);
		}

		if (!apkFile.exists()) {
			apkFile.createNewFile();
		}

		RandomAccessFile accessFile = new RandomAccessFile(apkFile, "rwd");
		accessFile.setLength(info.fileSize);
		accessFile.seek(resumeInfo.getDownloadedSize());
		return accessFile;
	}

}
